package ch.zbw.pra.sysventory.utils;

import java.io.Serializable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.EnumVariant;
import com.jacob.com.Variant;

/**
 * Klasse um alle möglichen Host zu finden. Via Sockets
 * 
 * @author Ralph Koster
 */

public class HostFinder implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -685162120721357672L;
	private static Logger LOG = LoggerFactory.getLogger(HostFinder.class);

	public static List<String> getAListOfAccessibleHosts(String address, String subnetMask) {
		List<String> accessibleHosts = new ArrayList<String>();
		SubnetUtils subnetUtils = new SubnetUtils(address, subnetMask);
		SubnetInfo subnetInfo = subnetUtils.getInfo();
		String[] hostIps = subnetInfo.getAllAddresses();
		for(String host : hostIps) {
			try {
				Socket socket = new Socket();
				InetSocketAddress socketAddress = new InetSocketAddress(host, 135);
				socket.connect(socketAddress, 200);
				socket.close();
				accessibleHosts.add(host);
			} catch (Exception e) {
				LOG.debug("Failed to connect to host " + host);
				continue;
			}
		}
		return accessibleHosts;
	}

	public static List<String> getLocalSubnets() {
		List<String> subnetMasks = new ArrayList<String>();
		String connectStr = String.format("winmgmts:\\\\%s\\root\\CIMV2", "localhost");
		String query = "SELECT * FROM Win32_NetworkAdapterConfiguration";
		
		try {
			ActiveXComponent axWMI = new ActiveXComponent(connectStr);
			Variant vCollection = axWMI.invoke("ExecQuery", new Variant(query));

			EnumVariant enumVariant = new EnumVariant(vCollection.toDispatch());
			Dispatch item = null;
			while (enumVariant.hasMoreElements()) {
				item = enumVariant.nextElement().toDispatch();
				// Dispatch.call returns a Variant which we can convert to a java form.
				String subnetMask = Dispatch.call(item, "IPSubnet").toString().trim();
				if(null != subnetMask && !"".equals(subnetMask) && !"null".equals(subnetMask)) {
					boolean duplicate = false;
					for(String tempSubnet : subnetMasks) {
						if(subnetMask.equals(tempSubnet)) {
							duplicate = true;
						}
					}
					if(!duplicate) {
						subnetMasks.add(subnetMask.trim());
					}
				}
			}
		} catch (Exception e) {
			LOG.debug("Failed to load subnets on localhost");
			LOG.error(e.toString());
		}
		return subnetMasks;
	}

	public static String getLocalAddress() {
		String address = "127.0.0.1";
		try {
			InetAddress inetAddress = InetAddress.getLocalHost();
			address = inetAddress.getHostAddress();
		} catch (UnknownHostException e) {
			LOG.debug("Failed to load local host address");
			LOG.error(e.toString());
		}
		return address;
	}
}
